package com.foreveross.bsl.common.utils.balance;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import com.foreveross.bsl.common.utils.balance.zookeeper2.ZKServiceKeeper;

/**
 *  zookeeper上所有的配置信息，watch动态更新配置
 * 
 * @author hyw
 *
 */
public class ZkCfg implements Serializable {
	
	private static final long serialVersionUID = 8928156507795492143L;
	
	public static final String SEPARATOR = "/";
	
	private String protocol; // https http
	private String host;
	private String port; 
	private String wsInfo; // context + api/v1
	
	private String serverList; // host1:port,host2:port,host3:port
	private int sessionTimeout; // 会话超时、心跳间隔
	
	private String rootNode; // 根节点  /app
	private Map<String, Boolean> dependencieNodes = new HashMap<String, Boolean>(); // 此web程序 依赖ws服务：默认contextPath
	
	private ZkNode nodes; // 离线数据 /app/.../...
	private ZKServiceKeeper zksk; // 实时zk策略
	
	private static ZkCfg zkfCfg; // 单列模型
	
	private ZkCfg() {}
	
	public static synchronized ZkCfg getInstance(Properties props) { // 根据配置文件对象初始化对象
		if(zkfCfg != null) {
			return zkfCfg;
		} 
		zkfCfg = new ZkCfg();
		if(props == null) 
			throw new RuntimeException("配置对象Properties不能为null！");
		
		zkfCfg.setProtocol(props.getProperty("zk.protocol", "http"));
		zkfCfg.setHost(props.getProperty("zk.host"));
		zkfCfg.setPort(props.getProperty("zk.port"));
		zkfCfg.setWsInfo(props.getProperty("zk.wsInfo")); // /api/v1
		zkfCfg.setServerList(props.getProperty("zk.serverList", "localhost:2181"));
		zkfCfg.setSessionTimeout(Integer.parseInt(props.getProperty("zk.sessionTimeout", "3000")));
		zkfCfg.setRootNode(props.getProperty("zk.rootNode"));
		String[] depends = props.getProperty("zk.dependencieNodes").replaceAll("^;|;$", "").trim().split(";");
		for (String den : depends) {
			zkfCfg.dependencieNodes.put(den, false);
		}
		return zkfCfg;
	}

	public synchronized ZkNode factorZkNode() {
		if(this.nodes == null) { 
			this.nodes = new ZkNode();
		}
		return this.nodes;
	}
	
	/** 递归读取app节点下所有配置信息
	 * @param znode
	 * @param zksk
	 */
	public void adapterZnode(ZkNode znode, ZKServiceKeeper zksk) {
		Map<String, String> rootMap = zksk.getServiceMap(znode.getPath());
		if(rootMap.size() == 0) {
			znode.setLast(true);
			return;
		}
		ZkNode otherServiceNode;
		for (String path: rootMap.keySet()) {
			otherServiceNode = new ZkNode();
			otherServiceNode.setzParent(znode);
			otherServiceNode.setName(path);
			otherServiceNode.setPath(znode.getPath() + ZkCfg.SEPARATOR + path);
			otherServiceNode.setData(rootMap.get(path));
			
			if(!znode.getzChilds().contains(otherServiceNode)) // 覆盖equals方法
				znode.addzChilds(otherServiceNode);
			// 递归添加节点
			this.adapterZnode(otherServiceNode, zksk);
		}
	}  
	
	public String getProtocol() {
		return protocol;
	}

	public void setProtocol(String protocol) {
		this.protocol = protocol;
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public String getPort() {
		return port;
	}

	public void setPort(String port) {
		this.port = port;
	}

	public String getWsInfo() {
		return wsInfo;
	}

	public void setWsInfo(String wsInfo) {
		this.wsInfo = wsInfo;
	}

	public String getServerList() {
		return serverList;
	}
	
	public void setServerList(String serverList) {
		this.serverList = serverList;
	}
	
	public int getSessionTimeout() {
		return sessionTimeout;
	}
	
	public void setSessionTimeout(int sessionTimeout) {
		this.sessionTimeout = sessionTimeout;
	}

	public String getRootNode() {
		return rootNode;
	}

	public void setRootNode(String rootNode) {
		this.rootNode = rootNode;
	}
	
	public ZkNode getNodes() {
		return nodes;
	}

	public void setNodes(ZkNode nodes) {
		this.nodes = nodes;
	}

	public Map<String, Boolean> getDependencieNodes() {
		return dependencieNodes;
	}

	public void setDependencieNodes(Map<String, Boolean> dependencieNodes) {
		this.dependencieNodes = dependencieNodes;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}

	public ZKServiceKeeper getZksk() {
		return zksk;
	}

	public void setZksk(ZKServiceKeeper zksk) {
		this.zksk = zksk;
	}
}
